#include "ProcesadorImagen.h"

bool ProcesadorImagen::esNegro(pixel unPixel) {
    bool pixelNegro = false;
    if (unPixel.r != 255 && unPixel.g != 255 && unPixel.b != 255) {
        pixelNegro = true;
    }
    return pixelNegro;
}

bool ProcesadorImagen::frameCorrecto(int xEmpiezaImagen, int xCorteImagen, int yInicial, int yFinal) {
    bool frameCorrecto = false;
    int ancho = xCorteImagen - xEmpiezaImagen;
    int alto = yFinal - yInicial;
    if (ancho > 0 && alto > 0) {
        frameCorrecto = true;
    }
    return frameCorrecto;

}

void ProcesadorImagen::verFrames() {
    vector<frame>::iterator it = this->frameImagenes.begin();

    for (; it != this->frameImagenes.end(); it++) {
        cout << "Frame para imagen: " << endl;
        cout << "xMin: " << (*it).xMin << endl;
        cout << "xMax: " << (*it).xMax << endl;
        cout << "yMin: " << (*it).yMin << endl;
        cout << "yMax: " << (*it).yMax << endl;
        cout << "Fin frame" << endl << endl;
    }

}


pixel** ProcesadorImagen::levantarImagenEnMatrizPixeles(const char* rutaOrig, long int* ancho, long int* alto, long int* despl) {
    FILE* fp = fopen(rutaOrig, "rb");
    if (fp == NULL) 
    {

        return NULL;
    }
    fseek(fp, CABECERA, SEEK_SET);
    fread(despl, sizeof (long), 1, fp);
    fseek(fp, 18L, SEEK_SET);
    fread(ancho, sizeof (long), 1, fp);
    fread(alto, sizeof (long), 1, fp);
    fseek(fp, (*despl), SEEK_SET);
    this->matPix = (pixel**) malloc(sizeof (pixel*)*(*ancho));
    for (int i = 0; i < (*ancho); i++) {
        *(this->matPix + i) = (pixel*) malloc(sizeof (pixel)*(*alto));
    }
    int padding = (*ancho) % 4;
    /*Se carga la matriz original sin PADDING*/
    for (int i = 0; i < (*alto); i++) {
        for (int j = 0; j < (*ancho); j++) {
            unsigned char r, g, b;
            this->matPix[j][i].r = 0;
            this->matPix[j][i].g = 0;
            this->matPix[j][i].b = 0;
            fread(&r, sizeof (char), 1, fp);
            fread(&g, sizeof (char), 1, fp);
            fread(&b, sizeof (char), 1, fp);
            this->matPix[j][i].r = r;
            this->matPix[j][i].g = g;
            this->matPix[j][i].b = b;
        }
        fseek(fp, padding, SEEK_CUR); /*Movimiento sobre el PADDING*/
    }
    fclose(fp);
    return this->matPix;
}

void ProcesadorImagen::guardarImagenDesdeMatrizPixeles(const char* rutaDest, const char* rutaOrig, pixel** matrizSave, long int ancho, long int alto, long int despl, long int padding) {
    FILE* fp = fopen(rutaOrig, "rb");
    FILE* fpo = fopen(rutaDest, "wb");
    /*Se escribe encabezado*/
    for (int i = 0; i < despl; i++)
        fputc(fgetc(fp), fpo);
    fclose(fp);
    /*Se reescribe el alto y el ancho(no es directamente el de la cabecera)*/
    fseek(fpo, 18L, SEEK_SET);
    fwrite(&ancho, sizeof (long), 1, fpo);
    fwrite(&alto, sizeof (long), 1, fpo);
    fseek(fpo, despl, SEEK_SET);
    //int padding=ancho%4;
    /*Se escribe en el archivo la imagen rotada*/
    for (int i = 0; i < alto; i++) {
        for (int j = 0; j < ancho; j++) {
            fwrite(&(matrizSave[j][i].r), sizeof (char), 1, fpo);
            fwrite(&(matrizSave[j][i].g), sizeof (char), 1, fpo);
            fwrite(&(matrizSave[j][i].b), sizeof (char), 1, fpo);
        }
        /*SE LE AGREGA EL PADDING*/
        unsigned char p = 0;
        for (int g = 0; g < padding; g++)
            fwrite(&p, sizeof (char), 1, fpo);
    }
    fclose(fpo);

}

int* ProcesadorImagen::obtenerVector(long int ancho, long int alto, int finX, int inicioX, int finY, int inicioY) {
    int cont = 0;
    int* vector = (int*) malloc(sizeof (int) *ancho * alto);
    for (int i = inicioY; i < finY; i++) {
        for (int j = inicioX; j < finX; j++) {
            unsigned char r, g, b;
            r = this->matPix[j][i].r;
            g = this->matPix[j][i].g;
            b = this->matPix[j][i].b;

            if (r == 255 && g == 255 && b == 255) {
                vector[cont] = 0;
            } else {
                vector[cont] = 1;
            }
            ++cont;
        }
    }
    return vector;
}

void ProcesadorImagen::boundingBox(string nombreImagen, long int ancho, long int alto) {

    // La recorro por columnas porque es mas facil para identificar los numeros
    // Voy obteniendo las caracteristicas de los frames de cada caracter.
    // Observacion: La matriz cargo la imagen con sistema de referencia (0,0) abajo, izquierda
    // es importante porque afecta en como armo el frame
    cout << "Se calcularan los frames de la imagen: " << nombreImagen << endl;

    bool primero = true; // nuevo frame para otra imagen
    int xEmpiezaImagen = 0, xCorteImagen = 0, yInicial = 0, yFinal = 0;
    for (int coordX = 0; coordX < ancho; coordX++) {
        int contadoBlancos = 0;
        for (int coordY = 0; coordY < alto; coordY++) {
            if (this->esNegro(this->matPix[coordX][coordY])) {
                if (primero) {
                    xEmpiezaImagen = coordX;
                    xCorteImagen = coordX;
                    yInicial = coordY;
                    yFinal = coordY;
                    primero = false;
                } else {
                    if (coordX < xEmpiezaImagen) {
                        xEmpiezaImagen = coordX;
                    }
                    if (coordX > xCorteImagen) {
                        xCorteImagen = coordX;
                    }
                    if (coordY < yInicial) {
                        yInicial = coordY;
                    }
                    if (coordY > yFinal) {
                        yFinal = coordY;
                    }
                }
            } else {
                contadoBlancos++;
            }
        }
        if (contadoBlancos == alto) {
            if (this->frameCorrecto(xEmpiezaImagen, xCorteImagen, yInicial, yFinal)) {
                frame nuevaImagen;
                nuevaImagen.xMin = xEmpiezaImagen-2;
                nuevaImagen.xMax = xCorteImagen+2;
                nuevaImagen.yMin = yInicial-2;
                nuevaImagen.yMax = yFinal+2;
                this->frameImagenes.push_back(nuevaImagen);
                this->cantidadDeImagenes++;
            }
            primero = true;
            xEmpiezaImagen = 0;
            xCorteImagen = 0;
            yInicial = 0;
            yFinal = 0;
        }
    }
}